/***************************************************************************//**
 * @file HID/HID_Joysticks.h
 * @author  Marek M. Cel <marekcel@mscsim.org>
 *
 * @section LICENSE
 *
 * Copyright (C) 2013 Marek M. Cel
 *
 * This file is part of MScSim. You can redistribute and modify it under
 * the terms of GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Further information about the GNU General Public License can also be found
 * on the world wide web at http://www.gnu.org.
 ******************************************************************************/
#ifndef HID_JOYSTICKS_H
#define HID_JOYSTICKS_H

////////////////////////////////////////////////////////////////////////////////

#include <iostream>
#include <string>

////////////////////////////////////////////////////////////////////////////////

#if defined(MSCSIM_DIRECTINPUT)
#   define MSCSIM_FORCEFEEDBACK
#endif

#define MSCSIM_MAX_JOYS_COUNT 8
#define MSCSIM_MAX_AXES_COUNT 16
#define MSCSIM_MAX_BUTT_COUNT 32

#define MSCSIM_AXIS_RANGE 32767.0f

////////////////////////////////////////////////////////////////////////////////

/**
 * This class handles joystick like input devices.
 * @see http://www.cs.cmu.edu/~jparise/directx/joystick/
 * @see http://msdn.microsoft.com/en-us/library/windows/desktop/ee417536%28v=vs.85%29.aspx
 */
class HID_Joysticks
{
public:

    /** */
    enum Axes
    {
        JoyAxisX = 0,       ///<  0: X-axis deflection
        JoyAxisY,           ///<  1: Y-axis deflection
        JoyAxisZ,           ///<  2: Z-axis deflection
        JoyAxisRX,          ///<  3: Rotation about X-axis
        JoyAxisRY,          ///<  4: Rotation about Y-axis
        JoyAxisRZ,          ///<  5: Rotation about Z-axis
        JoyAxisSlider1,     ///<  6: Slider 1
        JoyAxisSlider2,     ///<  7: Slider 2
        JoyAxisPOV1,        ///<  8: POV 1
        JoyAxisPOV2,        ///<  9: POV 2
        JoyAxisPOV3,        ///< 10: POV 3
        JoyAxisPOV4,        ///< 11: POV 4
        JoyAxisPOV5,        ///< 12: POV 5
        JoyAxisPOV6,        ///< 13: POV 6
        JoyAxisPOV7,        ///< 14: POV 7
        JoyAxisPOV8         ///< 15: POV 8
    };

    /** */
    struct Data
    {
        std::string name;   ///< device name
        
        float axis[ MSCSIM_MAX_AXES_COUNT ];    ///< -1.0 ... 1.0 normalized axis position
        int   butt[ MSCSIM_MAX_BUTT_COUNT ];    ///< 0: released, 1: pressed

        int   axisCount;    ///< number of device axes
        int   buttCount;    ///< number of devise buttons

        int   active;       ///< specifies active device
        int   force;        ///< specifies FF capable device
    };

    /** */
    static HID_Joysticks* getInstance()
    {
        if ( !m_instance )
        {
            m_instance = new HID_Joysticks();
        }

        return m_instance;
    }

    /** Destructor. */
    virtual ~HID_Joysticks();

    /**
     * This function initiate Joystick object.
     * @param platform dependent window identifier (used only in win32)
     */
    void init( void *winId = NULL );
    
    /** This function updates Joystick object. */
    void update();

    /** @return number of active joysticks */
    int getJoysCount() const;

    /**
     * @param joystick index number
     * @return joystick data
     */
    HID_Joysticks::Data getJoyData( int joyNum ) const;
    
#   ifdef MSCSIM_FORCEFEEDBACK
    /**
     * This function enables and disables ForceFeedback effects.
     * @param enabled
     */
    void setEffectsEnabled( int enabled );
#   endif

#   ifdef MSCSIM_FORCEFEEDBACK
    /**
     * @param joystick index number
     * @param normalized magnitude along x-axis <-1.0;1.0>
     * @param normalized magnitude along y-axis <-1.0;1.0>
     */
    void setEffectsMagnitude( int joyNum, float normX, float normY );
#   endif

private:

    static HID_Joysticks *m_instance;

    /**
     * You should use static function getInstance() due to get refernce
     * to Joytsicks class instance.
     */
    HID_Joysticks();

    /** Using this constructor is forbidden. */
    HID_Joysticks( const HID_Joysticks & ) {}

#   ifdef MSCSIM_FORCEFEEDBACK
    /** */
    void initForces( int joyNum );
#   endif

#   ifdef MSCSIM_FORCEFEEDBACK
    /** */
    void updateForces( int joyNum );
#   endif
};

////////////////////////////////////////////////////////////////////////////////

#endif // HID_JOYSTICKS_H
